use rtc::{
    rtp_session::SendRtpPacket,
    sdp::{Codec, Codecs, SdpSession, SdpSessionConfig},
    OpenSslContext,
};
use rtc::sdp::TransportType;
use rtc::sdp::RtcpMuxPolicy;
use sdp_types::{Direction, MediaType};
use sip_auth::{DigestAuthenticator, DigestCredentials, DigestUser};
use sip_core::{transport::udp::Udp, Endpoint};
use sip_core::transport::tcp::TcpConnector;
use sip_ua::{
    dialog::DialogLayer, invite::InviteLayer, Call, CallEvent, MediaEvent, RegistrarConfig,
    Registration, RtcMediaBackend,
};
use std::time::Duration;
use std::sync::Arc;
use tokio::{select, signal::ctrl_c, time::interval};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    env_logger::Builder::from_env(
        env_logger::Env::default().default_filter_or("info"),
    )
    .format_timestamp_secs()
    .init();

    log::info!("示例启动: make_call");

    let mut builder = Endpoint::builder();

    // Make a UDP transport
    log::info!("初始化 SIP 传输: UDP 0.0.0.0:5060");
    Udp::spawn(&mut builder, "0.0.0.0:5060").await.unwrap();

    // Enable TCP outbound factory so that ;transport=TCP 能被选择
    builder.add_transport_factory(Arc::new(TcpConnector::new()));

    // Add Dialog & INVITE capabilities
    log::debug!("添加 SIP 层: DialogLayer, InviteLayer");
    builder.add_layer(DialogLayer::default());
    builder.add_layer(InviteLayer::default());

    let endpoint = builder.build();
    log::info!("SIP Endpoint 构建完成");

    // Create credentials for user 1000
    log::info!("配置认证: 用户=1000, 域=192.168.43.252");
    let mut credentials = DigestCredentials::new();
    credentials.add_for_realm("192.168.43.252", DigestUser::new("1000", "1234"));

    // Register user 1000
    log::info!("开始注册到注册服务器 sip:192.168.43.252 (用户 1000)");
    let registration = Registration::register(
        endpoint,
        RegistrarConfig::new("1000".into(), "sip:192.168.43.252;transport=TCP".parse()?),
        DigestAuthenticator::new(credentials.clone()),
    )
    .await?;
    log::info!("注册成功");

    // Call 1003

    // Setup SDP session
    log::info!("创建 SDP 会话, 本地地址=192.168.43.252");
    let mut sdp_cfg = SdpSessionConfig::default();
    // 使用传统 RTP/AVP，避免对端不支持 DTLS-SRTP/AVPF 导致协商失败
    sdp_cfg.offer_transport = TransportType::Rtp;
    sdp_cfg.offer_avpf = false;
    // 显式设置 RTCP 复用策略为“协商”，对端支持则开启，不支持则回退
    sdp_cfg.rtcp_mux_policy = RtcpMuxPolicy::Negotiate;
    let mut sdp_session = SdpSession::new(OpenSslContext::try_new()?, "192.168.43.202".parse()?, sdp_cfg);

    // Define some audio codecs
    let audio = sdp_session
        .add_local_media(
            Codecs::new(MediaType::Audio)
                // .with_codec(Codec::G722)
                .with_codec(Codec::PCMU)
                .with_codec(Codec::PCMA)
                .with_dtmf(),
            Direction::SendRecv,
        )
        .unwrap();
    log::info!("配置音频编解码: G722/PCMU/PCMA (+DTMF), 方向=SendRecv");

    // Add an audio stream using the previously defined codecs
    sdp_session.add_media(audio, Direction::SendRecv);
    log::debug!("添加音频媒体流");

    log::info!("发起呼叫: 1003");
    let mut outbound_call = registration
        .make_call(
            "1003".into(),
            DigestAuthenticator::new(credentials.clone()),
            RtcMediaBackend::new(sdp_session),
        )
        .await?;
    log::info!("INVITE 已发送，等待响应或取消 (Ctrl+C)");

    // Wait for the call to be responded to, or cancel it
    let unacknowledged_call = select! {
        result = outbound_call.wait_for_completion() => {
            log::info!("收到 2xx 响应，准备完成呼叫建立 (发送 ACK)");
            result?
        },
        _ = ctrl_c() => {
            log::info!("收到 Ctrl+C，取消呼叫");
            outbound_call.cancel().await?;
            return Ok(());
        }
    };

    // Complete the call setup
    let call = unacknowledged_call.finish().await?;
    log::info!("呼叫已建立");

    call_event_loop(call).await?;

    Ok(())
}

async fn call_event_loop(
    mut call: Call<RtcMediaBackend>,
) -> Result<(), Box<dyn std::error::Error>> {
    // Enter the call event loop
    log::info!("进入呼叫事件循环");
    loop {
        match call.run().await? {
            CallEvent::Internal(event) => call.handle_internal_event(event).await?,
            CallEvent::Media(MediaEvent::ReceiverAdded {
                mut receiver,
                codec,
            }) => {
                // 协商结果可能是 G722/PCMU/PCMA，放开断言，仅记录
                log::info!("媒体接收器已添加: codec={}, pt={}", codec.name, codec.pt);

                tokio::spawn(async move {
                    log::debug!("接收任务启动");
                    while let Some(_rtp_packet) = receiver.recv().await {
                        // decode & play audio
                    }
                    log::debug!("接收任务结束");
                });
            }
            CallEvent::Media(MediaEvent::SenderAdded { mut sender, codec }) => {
                log::info!("媒体发送器已添加: codec={}, pt={}", codec.name, codec.pt);
                let max_mtu = call
                    .media()
                    .sdp_session()
                    .max_payload_size_for_media(sender.media_id())
                    .unwrap();
                log::debug!("最大负载大小 (MTU) = {} 字节", max_mtu);

                tokio::spawn(async move {
                    // send some audio
                    let mut interval = interval(Duration::from_millis(20));
                    log::debug!("发送任务启动: 周期=20ms");

                    loop {
                        let instant = interval.tick().await;

                        // Actually produce and encode some audio
                        let encoded_audio_data = vec![0u8; max_mtu];

                        sender
                            .send(SendRtpPacket::new(
                                instant.into(),
                                codec.pt,
                                encoded_audio_data.into(),
                            ))
                            .await
                            .unwrap();
                    }
                });
            }
            CallEvent::Terminated => {
                log::info!("呼叫已结束");
                return Ok(());
            }
        }
    }
}
